/*********************************************************************************
 *      Copyright:  (C) 2025 LingYun<iot25@lingyun>
 *                  All rights reserved.
 *
 *       Filename:  main.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(24/04/25)
 *         Author:  LingYun <iot25@lingyun>
 *      ChangeLog:  1, Release initial version on "24/04/25 14:31:06"
 *                 
 ********************************************************************************/

#include "main.h"
#include "socket.h"
#include "sqlite.h"
#include "thread.h"
#include "logger.h"


// 全局变量
int g_server_running = 1;
sqlite3 *g_db = NULL;




int main(int argc, char **argv)
{
    int sockfd = -1;
    int clifd = -1;
    int rv = -1;
    struct sockaddr_in servaddr;
    struct sockaddr_in cliaddr;
    int port = DEFAULT_PORT;
    int ch;
    struct option opts[] = {
        {"port", required_argument, NULL, 'p'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}
    };
    socklen_t cli_len = sizeof(cliaddr);
    pthread_t pid;
    
    // 解析命令行参数
    while ((ch = getopt_long(argc, argv, "p:h", opts, NULL)) != -1) {
        switch (ch) {
            case 'p':
                port = atoi(optarg);
                break;
            case 'h':
                print_usage(argv[0]);
                return 0;
        }
    }
    
    if (port <= 0) {
        print_usage(argv[0]);
        return -1;
    }
    
    // 设置信号处理函数
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
    
    // 初始化数据库
    if (init_database() < 0) {
        fprintf(stderr, "Failed to initialize database\n");
        return -1;
    }
    
    // 创建套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        fprintf(stderr, "Create socket failure: %s\n", strerror(errno));
        return -1;
    }
    
    printf("Created socket[%d] successfully\n", sockfd);
    
    // 设置地址重用
    int opt = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    
    // 绑定地址和端口
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(port);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    
    rv = bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    if (rv < 0) {
        fprintf(stderr, "Socket[%d] bind to port[%d] failure: %s\n",
                sockfd, port, strerror(errno));
        return -1;
    }
    
    printf("Bind successful\n");
    
    // 监听连接
    rv = listen(sockfd, MAX_CLIENTS);
    if (rv < 0) {
        fprintf(stderr, "Socket listen failure: %s\n", strerror(errno));
        return -1;
    }
    
    printf("Socket listen on port[%d] successful\n", port);
    
    // 主循环，接受客户端连接
    while (g_server_running) 
	{
        printf("Waiting for clients...\n");
        
        clifd = accept(sockfd, (struct sockaddr *)&cliaddr, &cli_len);
        if (clifd < 0) {
            if (errno == EINTR) {
                // 被信号中断，检查服务器是否仍在运行
                if (!g_server_running) {
                    break;
                }
                continue;
            }
            fprintf(stderr, "Accept a new client failure: %s\n", strerror(errno));
            continue;
        }
        
        printf("Accepted a new client[%s,%d] with fd[%d]\n",
               inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port), clifd);
        
        // 为每个客户端创建一个处理线程
        int *arg = malloc(sizeof(int));
        if (arg == NULL) {
            fprintf(stderr, "Malloc failure: %s\n", strerror(errno));
            close(clifd);
            continue;
        }
        
        *arg = clifd;
        
        if (thread_client(&pid, client_handler, arg)) {
            fprintf(stderr, "Pthread create failure: %s\n", strerror(errno));
            free(arg);
            close(clifd);
        }
    }
    
    // 清理资源
    if (sockfd >= 0) {
        close(sockfd);
    }
    
    if (g_db) {
        sqlite3_close(g_db);
    }
    
    return 0;
}

void print_usage(char *progname)
{
    printf("%s usage:\n", progname);
    printf("--port or -p: specify server port (default: %d)\n", DEFAULT_PORT);
    printf("--help or -h: print this information\n");
}



void signal_handler(int signo)
{
    printf("Received signal %d, shutting down server...\n", signo);
    g_server_running = 0;
}








